<template>
  <div
    class="inches-input-box"
    :style="styleData"
    :class="{ 'inches-input-disabled': isDisabled || valDisable }"
  >
    <input
      v-model="inputShowValue"
      ref="unitInputRef"
      class="unitInput"
      :class="{ 'input-error': !isOK, 'input-slot': isHaveNumberBtn }"
      autocomplete="off"
      :disabled="isDisabled || valDisable"
      @focus="focusInputToSelectAll"
      @input="inputEvent"
      @compositionstart="inputStart"
      @compositionend="inputEnd"
      @change="changeValueFun"
    />
    <div
      v-if="isHaveNumberBtn"
      slot="suffix"
      :class="{
        'slot-icon-div': true,
        'slot-icon-editable': !isDisabled && !valDisable,
      }"
    >
      <i class="iconfont icon-shangla" @click.stop="handleValueUp" />
      <i class="iconfont icon-xiala" @click.stop="handleValueDown" />
    </div>
  </div>
</template>

<script>
import { TzLengthSetting, TzLengthUnit } from "./inchesExchange";
export default {
  props: {
    // 输入框是否可清空，默认为不可清空
    clearable: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 输入框是否禁用
    isDisabled: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 传入的单位值（毫米、英寸英尺）
    inchesVal: [String, Number],
    // 没有英尺部分（英尺转换为英寸，再返回值）
    isNoneFeet: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 传入最大值（mm，Number）
    mmMax: {
      type: Number,
      required: false,
    },
    // 传入最小值（mm，Number）
    mmMin: {
      type: Number,
      required: false,
    },
    // 传入的样式，部分生效（不针对el_inner之类的属性）
    styleData: {
      type: Object,
      default() {
        return {};
      },
    },
    // 长度单位，默认毫米
    lengthUnit: {
      type: Number,
      default: 2,
    },
    // 是否四舍五入英寸的分数部分
    isMathRoundGrade: {
      type: Boolean,
      default: false,
    },
    // 英制分数的最大分母
    lengthDenominator: {
      type: Number,
      default: 64,
    },
    // 是否有改值回调（有就不需要超值提示）
    isHaveValueChangeCallback: {
      default: false,
    },
    // 是否有加减值快捷按钮
    isHaveNumberBtn: {
      type: Boolean,
      default: true,
    },
    // 加减的单次值
    plusAndMminusValue: {
      type: Number,
      default: 0,
    },
  },
  components: {},
  data() {
    return {
      // 1.纯数字 => ^[\d]+[\d]$
      // 2.英尺：10' => ^[\d]+\'$
      // 3.英尺英寸： 10’8" => ^[\d]+\'+[\d]+\"$
      // 4.英寸：8" => ^[\d]+\"$
      // 5.分数：4/5" => ^[\d]+\/+[\d]+\"$
      // 6.英寸 分数：8 4/5" => ^[\d]+\s+[\d]+\/+[\d]+\"$
      // 7.英尺 分数：8'4/5" => ^[\d]+\'+[\d]+\/+[\d]+\"$
      // 8.英尺 英寸 分数： 10'8 4/5" => ^[\d]+\'+[\d]+\s+[\d]+\/+[\d]+\"$
      // 9.带有小数的格式: 4.5',4.5'3.5",3.5",4.5'1 1/3",4.5'1",4.5'1.5"
      mmValue: "", // 毫米为单位的值
      feetInchesValue: "", // 英尺英寸单位的值
      onlyInchesValue: "", // 英寸单位的值
      inputShowValue: "", // input显示的值
      isOnComposed: false, // 是否输入组成中
      isOK: true, // 输入内容格式是否正确
      messages: {
        message: "",
        code: "",
        data: {
          inchesVal: "",
          mmVal: "",
        },
      }, // 改值后返回的信息
      lastValInfo: {}, // 上一次输入值的有效结果
      valDisable: false, // 是否可更改值
      plusAndMminusValueDefault: 50.8, // 默认两英寸，一英寸（1"） = 25.4毫米（mm）
    };
  },
  mounted() {
    if (
      this.mmMax !== undefined &&
      this.mmMax !== null &&
      !isNaN(this.mmMax) &&
      (this.mmMax === 0 || this.mmMax === "0")
    ) {
      this.valDisable = true;
    }
    if (
      this.mmMin !== undefined &&
      this.mmMin !== null &&
      !isNaN(this.mmMin) &&
      (this.mmMin === 0 || this.mmMin === "0")
    ) {
      this.valDisable = true;
    }
    this.initValFun(this.inchesVal);
  },
  beforeDestroy() {},
  computed: {},
  watch: {
    // 传入值变化时，重新转换显示
    inchesVal(val) {
      let that = this;
      that.initValFun(val);
    },
    // 长度单位切换后，需要切换展示的值的格式
    lengthUnit(val) {
      let that = this;
      that.exchangeShowValFun(that, val);
    },
  },
  methods: {
    // #region 操作
    // 操作：选中input框，自动全选
    focusInputToSelectAll() {
      this.$refs.unitInputRef.select();
      this.$emit("focus");
    },
    changeInputValue(val) {
      this.initValFun(val);
    },
    // 初始化传入的值
    initValFun(val) {
      this.mmValue = val;
      this.feetInchesValue = val;
      this.onlyInchesValue = val;
      this.inputShowValue = val;
      if (val && val !== "0") {
        if (Number(val)) {
          // 纯数字 => 英尺英寸单位、英寸单位
          // if ((this.mmMax !== undefined && this.mmMax !== null && !isNaN(this.mmMax)) && this.mmValue > this.mmMax) this.mmValue = this.mmMax
          // if ((this.mmMin !== undefined && this.mmMin !== null && !isNaN(this.mmMin)) && this.mmValue < this.mmMin) this.mmValue = this.mmMin
          this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
            this.mmValue,
            false,
            this.isMathRoundGrade ? 1 : this.lengthDenominator
          );
          this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
            this.mmValue,
            true,
            this.isMathRoundGrade ? 1 : this.lengthDenominator
          );
          this.exchangeShowValFun(this, this.lengthUnit);
        } else {
          // 非纯数字 => 毫米单位 => 英尺英寸
          this.mmValue = TzLengthSetting.inchesToMilliMeter(val);
          // if ((this.mmMax !== undefined && this.mmMax !== null && !isNaN(this.mmMax)) && this.mmValue > this.mmMax) this.mmValue = this.mmMax
          // if ((this.mmMin !== undefined && this.mmMin !== null && !isNaN(this.mmMin)) && this.mmValue < this.mmMin) this.mmValue = this.mmMin
          this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
            this.mmValue,
            false,
            this.isMathRoundGrade ? 1 : this.lengthDenominator
          );
          this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
            this.mmValue,
            true,
            this.isMathRoundGrade ? 1 : this.lengthDenominator
          );
          this.exchangeShowValFun(this, this.lengthUnit);
        }
      }
      // 存储传入的值
      this.lastValInfo = {
        mmValue: this.mmValue,
        feetInchesValue: this.feetInchesValue,
        onlyInchesValue: this.onlyInchesValue,
        inputShowValue: this.inputShowValue,
      };
    },
    // 方法：切换输入框显示的值
    exchangeShowValFun(that, value) {
      switch (value) {
        case TzLengthUnit.MM:
          // that.inputShowValue = Math.round(that.mmValue * 100) / 100
          that.inputShowValue = Math.round(that.mmValue * 10) / 10;
          break;
        case TzLengthUnit.FEET_INCHES:
          that.inputShowValue = that.feetInchesValue;
          break;
        case TzLengthUnit.INCHES:
          that.inputShowValue = that.onlyInchesValue;
          break;
        default:
          // that.inputShowValue = Math.round(that.mmValue * 100) / 100
          that.inputShowValue = Math.round(that.mmValue * 10) / 10;
          break;
      }
      // console.log('单位切换', value, that.inputShowValue, { feetInchesValue: that.feetInchesValue, onlyInchesValue: that.onlyInchesValue, mmValue: that.mmValue })
    },
    // 输入框的单个输入事件 [中文是多次输入，结果一个]
    // input事件：输入框值变化时
    inputEvent() {
      if (this.isOnComposed) {
        return;
      }
      if (this.inputShowValue === 0 || this.inputShowValue === "0") {
        this.isOK = true;
      } else {
        this.inputShowValue = TzLengthSetting.adjustInchesInput(
          this.inputShowValue
        );
        if (this.inputShowValue === "") {
          this.isOK = true;
        } else {
          this.isOK = TzLengthSetting.reg.test(this.inputShowValue);
        }
      }
    },
    // 中文拼音：开始输入
    inputStart() {
      this.isOnComposed = true;
    },
    // 中文拼音：输入完毕
    inputEnd() {
      this.isOnComposed = false;
    },
    // 输入框值改变后，修改状态为false
    changeValueFun() {
      if (this.inputShowValue === "") {
        this.inputShowValue = this.lastValInfo.inputShowValue;
        this.mmValue = this.lastValInfo.mmValue;
        this.feetInchesValue = this.lastValInfo.feetInchesValue;
        this.onlyInchesValue = this.lastValInfo.onlyInchesValue;
        return;
      }
      if (this.inputShowValue === 0 || this.inputShowValue === "0") {
        this.mmValue = 0;
        this.feetInchesValue = "0";
        this.onlyInchesValue = "0";
        if (
          this.mmMin !== undefined &&
          this.mmMin !== null &&
          !isNaN(this.mmMin) &&
          this.mmValue < this.mmMin
        ) {
          this.mmValue = this.mmMin;
          if (!this.isHaveValueChangeCallback) {
            this.overValueAreaFun(); // 超过最大最小值时的消息回调
          }
        }
        this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
          this.mmValue,
          true,
          this.isMathRoundGrade ? 1 : this.lengthDenominator
        ); // 再毫米转英尺英寸
        this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
          this.mmValue,
          false,
          this.isMathRoundGrade ? 1 : this.lengthDenominator
        ); // 再毫米转英寸
        this.exchangeShowValFun(this, this.lengthUnit);
        this.lastValInfo = {
          mmValue: this.mmValue,
          feetInchesValue: this.feetInchesValue,
          onlyInchesValue: this.onlyInchesValue,
          inputShowValue: this.inputShowValue,
        };
        this.messages = {
          // message: this.$t('message.conversionSucceeded'),
          code: 1,
          data: {
            inchesVal: this.feetInchesValue,
            mmVal: this.mmValue,
          },
        };
        this.$emit("returnInchesVal", this.messages);
        return;
      }
      this.isOK = TzLengthSetting.reg.test(this.inputShowValue);
      this.inputShowValue = TzLengthSetting.formatValue(this.inputShowValue);
      if (!this.isOK) {
        this.mmValue = "";
        this.feetInchesValue = "";
        this.onlyInchesValue = "";
        this.messages = {
          // message: this.$t('message.inputFormatError'),
          code: 0,
          data: {
            inchesVal: this.feetInchesValue,
            mmVal: this.mmValue,
          },
        };
        this.$emit("returnInchesVal", this.messages);
        return;
      }
      // 不是纯数字（及不包含浮点数）的就转换为毫米单位，并返回
      if (!Number(this.inputShowValue)) {
        this.feetInchesValue = this.inputShowValue;
        this.mmValue = TzLengthSetting.inchesToMilliMeter(this.feetInchesValue);
        if (
          this.mmMax !== undefined &&
          this.mmMax !== null &&
          !isNaN(this.mmMax) &&
          this.mmValue > this.mmMax
        ) {
          this.mmValue = this.mmMax;
          if (!this.isHaveValueChangeCallback) {
            this.overValueAreaFun(); // 超过最大最小值时的消息回调
          }
        }
        if (
          this.mmMin !== undefined &&
          this.mmMin !== null &&
          !isNaN(this.mmMin) &&
          this.mmValue < this.mmMin
        ) {
          this.mmValue = this.mmMin;
          if (!this.isHaveValueChangeCallback) {
            this.overValueAreaFun(); // 超过最大最小值时的消息回调
          }
        }
        this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
          this.mmValue,
          false,
          this.isMathRoundGrade ? 1 : this.lengthDenominator
        ); // 再毫米转英尺英寸
        this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
          this.mmValue,
          true,
          this.isMathRoundGrade ? 1 : this.lengthDenominator
        ); // 再毫米转英寸
        this.exchangeShowValFun(this, this.lengthUnit);
        this.lastValInfo = {
          mmValue: this.mmValue,
          feetInchesValue: this.feetInchesValue,
          onlyInchesValue: this.onlyInchesValue,
          inputShowValue: this.inputShowValue,
        };
        this.messages = {
          code:
            this.feetInchesValue &&
            (Number(this.mmValue) || parseFloat(this.mmValue))
              ? 1
              : 0,
          // message:
          //   this.feetInchesValue &&
          //   (Number(this.mmValue) || parseFloat(this.mmValue))
          //     ? this.$t('message.conversionSucceeded')
          //     : this.$t('message.conversionFailed'),
          data: {
            inchesVal: this.feetInchesValue,
            mmVal: Number(this.mmValue) || parseFloat(this.mmValue),
          },
        };
        this.$emit("returnInchesVal", this.messages);
        return;
      }
      // 是毫米，就转换为英尺英寸
      this.mmValue = this.inputShowValue;
      if (
        this.mmMax !== undefined &&
        this.mmMax !== null &&
        !isNaN(this.mmMax) &&
        this.mmValue > this.mmMax
      ) {
        this.mmValue = this.mmMax;
        if (!this.isHaveValueChangeCallback) {
          this.overValueAreaFun(); // 超过最大最小值时的消息回调
        }
      }
      if (
        this.mmMin !== undefined &&
        this.mmMin !== null &&
        !isNaN(this.mmMin) &&
        this.mmValue < this.mmMin
      ) {
        this.mmValue = this.mmMin;
        if (!this.isHaveValueChangeCallback) {
          this.overValueAreaFun(); // 超过最大最小值时的消息回调
        }
      }
      this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
        this.mmValue,
        true,
        this.isMathRoundGrade ? 1 : this.lengthDenominator
      ); // 再毫米转英尺英寸
      this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
        this.mmValue,
        false,
        this.isMathRoundGrade ? 1 : this.lengthDenominator
      ); // 再毫米转英寸
      this.exchangeShowValFun(this, this.lengthUnit);
      this.lastValInfo = {
        mmValue: this.mmValue,
        feetInchesValue: this.feetInchesValue,
        onlyInchesValue: this.onlyInchesValue,
        inputShowValue: this.inputShowValue,
      };
      this.messages = {
        // message: this.$t('message.conversionSucceeded'),
        code: 1,
        data: {
          inchesVal: this.feetInchesValue,
          mmVal: Number(this.mmValue),
        },
      };
      this.$emit("returnInchesVal", this.messages);
    },
    // 超过最大最小值时的消息回调
    overValueAreaFun() {
      this.$emit("verifyFailed", { mmMin: this.mmMin, mmMax: this.mmMax });
    },
    // 操作：增加值
    handleValueUp() {
      if (this.isDisabled || this.valDisable) {
        return;
      }
      let mm =
        Number(this.mmValue) +
        (this.plusAndMminusValue
          ? this.plusAndMminusValue
          : this.plusAndMminusValueDefault);
      if (
        this.mmMax !== undefined &&
        this.mmMax !== null &&
        !isNaN(this.mmMax) &&
        mm > this.mmMax
      ) {
        mm = this.mmMax;
      }
      // 与上一次的毫米值的相等，则退出
      if (
        (this.lastValInfo.mmValue || Number(this.lastValInfo.mmValue) === 0) &&
        mm === Number(this.lastValInfo.mmValue)
      ) {
        return;
      }
      this.mmValue = mm;
      this.updateValue(); // 加减的赋值更新
    },
    // 操作：减少值
    handleValueDown() {
      if (this.isDisabled || this.valDisable) {
        return;
      }
      let mm =
        Number(this.mmValue) -
        (this.plusAndMminusValue
          ? this.plusAndMminusValue
          : this.plusAndMminusValueDefault);
      if (mm < 0) {
        return;
      }
      if (
        this.mmMin !== undefined &&
        this.mmMin !== null &&
        !isNaN(this.mmMin) &&
        mm < this.mmMin
      ) {
        mm = this.mmMin;
      }
      // 与上一次的毫米值的相等，则退出
      if (
        (this.lastValInfo.mmValue || Number(this.lastValInfo.mmValue) === 0) &&
        mm === Number(this.lastValInfo.mmValue)
      ) {
        return;
      }
      this.mmValue = mm;
      this.updateValue(); // 加减的赋值更新
    },
    // 加减的赋值更新
    updateValue() {
      this.feetInchesValue = TzLengthSetting.milliMeterToInchesFun(
        this.mmValue,
        false,
        this.isMathRoundGrade ? 1 : this.lengthDenominator
      );
      this.onlyInchesValue = TzLengthSetting.milliMeterToInchesFun(
        this.mmValue,
        true,
        this.isMathRoundGrade ? 1 : this.lengthDenominator
      );
      this.exchangeShowValFun(this, this.lengthUnit);
      this.lastValInfo = {
        mmValue: this.mmValue,
        feetInchesValue: this.feetInchesValue,
        onlyInchesValue: this.onlyInchesValue,
        inputShowValue: this.inputShowValue,
      };
      this.messages = {
        code:
          this.feetInchesValue &&
          (Number(this.mmValue) || parseFloat(this.mmValue))
            ? 1
            : 0,
        // message:
        //   this.feetInchesValue &&
        //   (Number(this.mmValue) || parseFloat(this.mmValue))
        //     ? this.$t('message.conversionSucceeded')
        //     : this.$t('message.conversionFailed'),
        data: {
          inchesVal: this.feetInchesValue,
          mmVal: Number(this.mmValue) || parseFloat(this.mmValue),
        },
      };
      this.$emit("returnInchesVal", this.messages);
    },
    // #endregion
  },
};
</script>

<style lang="less"></style>

<style lang="less" scoped>
@height: 28px;
@color: #fdb906;
.inches-input-box {
  width: 124px;
  height: @height;
  position: relative;
  input {
    width: 100%;
    height: @height;
    line-height: @height;
    border-radius: 4px;
    padding: 0 5px;
    -webkit-appearance: none;
    background-image: none;
    border: 1px solid #dcdfe6;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    color: #606266;
    display: inline-block;
    font-size: inherit;
    outline: none;
    -webkit-transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
    transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
    overflow: visible;
  }
  input:focus {
    border-color: @color;
  }
  .input-error {
    border-color: red;
  }
  .input-slot {
    padding-right: 20px;
  }
  .slot-icon-div {
    width: 15px;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    align-items: center;
    position: absolute;
    right: 5px;
    top: 0;
    bottom: 0;
    i {
      cursor: pointer;
      font-size: 12px;
      color: #c0c4cc;
      &:hover {
        color: @color;
      }
    }
  }
  .slot-icon-editable {
    i {
      cursor: pointer;
      &:hover {
        color: @color;
      }
    }
  }
}
.inches-input-normal {
  &:hover {
    input {
      border-color: @color;
    }
  }
}
.inches-input-disabled {
  input {
    cursor: not-allowed;
    background-color: #f5f7fa;
  }
}
</style>
